﻿using System;
using System.Threading;
using fastCSharp;
using fastCSharp.diagnostics;

namespace diantou.dataServer
{
    /// <summary>
    /// 数据服务控制台
    /// </summary>
    class server : fastCSharp.diagnostics.consoleLog
    {
        /// <summary>
        /// 轮询服务
        /// </summary>
        private diantou.dataAccess.tcpServer.Poll pollServer;
        /// <summary>
        /// 数据读取服务
        /// </summary>
        private diantou.dataAccess.tcpServer.DataAccess dataServer;
        /// <summary>
        /// 数据日志服务
        /// </summary>
        private diantou.dataAccess.tcpServer.DataLog dataLogServer;
        /// <summary>
        /// 数据写服务
        /// </summary>
        private diantou.dataAccess.tcpServer.DataWrite writeServer;
        /// <summary>
        /// OJ数据服务
        /// </summary>
        private diantou.dataAccess.onlineJudgeData.tcpServer ojDataServer;
        /// <summary>
        /// 是否已经存在数据服务进程
        /// </summary>
        private bool isTryIgnore;
        /// <summary>
        /// 当前进程是否正在尝试忽略数据写服务操作
        /// </summary>
        private bool isTryIgnoreDataWriter;
        /// <summary>
        /// 当前进程是否正在尝试忽略数据读取服务操作
        /// </summary>
        private bool isTryIgnoreDataReader;
        /// <summary>
        /// 启动服务
        /// </summary>
        protected override void start()
        {
            if (fastCSharp.sql.connection.IsCheckConnection)
            {
                isTryIgnore = false;
                try
                {
                    diantou.dataAccess.tcpCall.questionDraft.saveMemoryCache();
                    diantou.dataAccess.tcpCall.programDraft.saveMemoryCache();
                    isTryIgnore = true;
                }
                catch (Exception error)
                {
                    output(error);
                }
                finally { write(); }
            }
            else output("没有找到可用的数据库连接信息");
        }
        /// <summary>
        /// 启动数据写服务
        /// </summary>
        private void write()
        {
            bool isStart = false;
            try
            {
                isStart = (writeServer = new diantou.dataAccess.tcpServer.DataWrite()).Start();
                writeServer.OnIgnoreGroup += groupId =>
                {
                    if (groupId == 0 && !isTryIgnoreDataWriter)
                    {
                        diantou.dataAccess.tcpServer.DataWrite server = Interlocked.Exchange(ref writeServer, null);
                        if (server != null)
                        {
                            server.StopListen();
                            fastCSharp.threading.threadPool.TinyPool.Start(() =>
                            {
                                output("停止服务 DataWrite");
                                pub.Dispose(ref server);
                            });
                        }
                    }
                };
            }
            catch (Exception error)
            {
                output(error);
            }
            output("DataWrite " + isStart.ToString());
            if (isStart)
            {
                if (isTryIgnore)
                {
                    isTryIgnoreDataWriter = true;
                    try
                    {
                        diantou.dataAccess.tcpClient.DataWrite.TcpIgnoreGroup(int.MaxValue);
                        diantou.dataAccess.tcpClient.DataWrite.TcpIgnoreGroup(0);
                    }
                    catch (Exception error)
                    {
                        output(error);
                    }
                    finally { isTryIgnoreDataWriter = false; }
                }
                output("等待数据加载...");
                diantou.dataAccess.user.WaitLoad();
                output("数据加载完毕...");
                data();
            }
            else
            {
                writeServer = null;
                fastCSharp.threading.timerTask.Default.Add(write, date.NowSecond.AddSeconds(5));
            }
        }
        /// <summary>
        /// 启动数据读取服务
        /// </summary>
        private void data()
        {
            bool isStart = false;
            try
            {
                if (isStart = (dataServer = new diantou.dataAccess.tcpServer.DataAccess()).Start())
                {
                    setTcpIgnoreGroup(() => dataServer, () => isTryIgnoreDataReader, () =>
                    {
                        diantou.dataAccess.tcpServer.DataLog dataLog = dataLogServer;
                        if (dataLog != null) dataLog.StopListen();
                        diantou.dataAccess.tcpServer.Poll poll = pollServer;
                        if (poll != null) poll.StopListen();
                    });
                }
            }
            catch (Exception error)
            {
                output(error);
            }
            output("DataAccess " + isStart.ToString());
            if (isStart)
            {
                dataLog();
                poll();
                ojData();
                if (isTryIgnore)
                {
                    isTryIgnoreDataReader = true;
                    try
                    {
                        diantou.dataAccess.tcpClient.DataAccess.TcpIgnoreGroup(int.MaxValue);
                        diantou.dataAccess.tcpClient.DataAccess.TcpIgnoreGroup(0);
                    }
                    catch (Exception error)
                    {
                        output(error);
                    }
                    finally { isTryIgnoreDataReader = false; }
                }
                //fastCSharp.threading.timerTask.Default.Add(checkMemory, date.NowSecond.AddHours(1));
            }
            else
            {
                dataServer = null;
                fastCSharp.threading.timerTask.Default.Add(data, date.NowSecond.AddSeconds(5));
            }
        }
        /// <summary>
        /// 启动数据日志服务
        /// </summary>
        private void dataLog()
        {
            bool isStart = false;
            try
            {
                isStart = (dataLogServer = new diantou.dataAccess.tcpServer.DataLog()).Start();
            }
            catch (Exception error)
            {
                output(error);
            }
            output("DataLog " + isStart.ToString());
            if (!isStart)
            {
                dataLogServer = null;
                fastCSharp.threading.timerTask.Default.Add(dataLog, date.NowSecond.AddSeconds(5));
            }
        }
        /// <summary>
        /// 启动轮询服务
        /// </summary>
        private void poll()
        {
            bool isStart = false;
            try
            {
                isStart = (pollServer = new diantou.dataAccess.tcpServer.Poll()).Start();
            }
            catch (Exception error)
            {
                output(error);
            }
            output("Poll " + isStart.ToString());
            if (!isStart)
            {
                pollServer = null;
                fastCSharp.threading.timerTask.Default.Add(poll, date.NowSecond.AddSeconds(5));
            }
        }
        /// <summary>
        /// OJ数据服务
        /// </summary>
        private void ojData()
        {
            bool isStart = false;
            try
            {
                isStart = (ojDataServer = new dataAccess.onlineJudgeData.tcpServer()).Start();
            }
            catch (Exception error)
            {
                output(error);
            }
            output("OJ Data " + isStart.ToString());
            if (!isStart)
            {
                ojDataServer = null;
                fastCSharp.threading.timerTask.Default.Add(ojData, date.NowSecond.AddSeconds(5));
            }
        }
        ///// <summary>
        ///// 内存泄漏检测
        ///// </summary>
        //private void checkMemory()
        //{
        //    try
        //    {
        //        fastCSharp.memoryGraph.memoryInfo memory = fastCSharp.memoryGraph.GetMemoryInfo();
        //        if (memory.Total > (100L << 30))
        //        {
        //            if ((int)(memory.Avail >> 30) <= (date.Now.Hour == 5 ? 30 : 10) && (fastCSharp.diagnostics.process.GetProcessMemoryInfo().WorkingSetSize >> 30) >= 10)
        //            {
        //                fastCSharp.diagnostics.process.StartCurrent();
        //                return;
        //            }
        //        }
        //    }
        //    catch (Exception error)
        //    {
        //        output(error);
        //    }
        //    fastCSharp.threading.timerTask.Default.Add(checkMemory, date.NowSecond.AddHours(1));
        //}
        /// <summary>
        /// 关闭服务
        /// </summary>
        protected override void dispose()
        {
            pub.Dispose(ref writeServer);
            pub.Dispose(ref dataLogServer);
            pub.Dispose(ref pollServer);
            pub.Dispose(ref dataServer);
            pub.Dispose(ref ojDataServer);
        }
    }
}
